﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Windows.Forms;
using System.Xml;
using SdmxMl.Common;
using SdmxMl.Helper;
using SdmxMl.Manager;
using SdmxMl.Structure;

namespace SdmxMl.GenericMetadata
{
    /// <summary>
    /// The attribute value set provides the values for a set of metadata attributes
    /// reported against a target identifier key. The TargetRef element contains the
    /// value of the metadata attribute's target attribute in the metadata structure
    /// definition (that is, the ID of the full or partial target identifier which is
    /// the target of the metadata report). TargetValues is an element substructure
    /// which provides the specific full or partial target identifier component values,
    /// and the ReportedAttribute sub-element allows for values to be reported against
    /// the metadata attributes as described in the referenced metadata structure
    /// definition for the referenced full or partial targets.
    /// </summary>
    public class AttributeValueSetType : ISearchIdName   
    {
        #region Properties

        public MetadataSetType ParentMetadataSet { get; set; }

        private string _targetRef;
        public string TargetRef
        {
            get { return _targetRef; }
            set { _targetRef = value; }
        }
        private ReportedAttributeTypeList _reportedAttributeList;
        public ReportedAttributeTypeList ReportedAttributeList
        {
            get { return _reportedAttributeList; }
        }

        private ComponentValueTypeList _targetValuesTypeList;
        public ComponentValueTypeList TargetValuesTypeList
        {
            get { return _targetValuesTypeList; }
        }

        #endregion //Properties

        #region Cloning

        public AttributeValueSetType Clone()
        {
            AttributeValueSetType clone = new AttributeValueSetType(ParentMetadataSet);
            clone.TargetRef = TargetRef;
            clone.TargetValuesTypeList.Clear();
            foreach (ReportedAttributeType ra in _reportedAttributeList)
                clone.ReportedAttributeList.Add(ra.Clone());
            foreach (ComponentValueType cv in _targetValuesTypeList)
                clone.TargetValuesTypeList.Add(cv.Clone());

            return clone;
        }

        #endregion


        #region Construction

        public AttributeValueSetType(MetadataSetType meta)
        {
            Init(meta);
            // One required
            _targetValuesTypeList.Add(new ComponentValueType());
        }

        private MultiLang nameML;
        private void Init(MetadataSetType meta)
        {
            ParentMetadataSet = meta;
            _targetValuesTypeList = new ComponentValueTypeList();
            _reportedAttributeList = new ReportedAttributeTypeList();
            nameML = new MultiLang("");
        }

        public AttributeValueSetType(XmlNode nodeArtefact, XmlNamespaceManager nsmgr, MetadataSetType meta)
        {
            Init(meta);
            _targetRef = Xmlhelper.GetNodeText(nodeArtefact, "./genericmetadata:TargetRef", nsmgr);
            XmlNode nodeTargetValues = nodeArtefact.SelectSingleNode("./genericmetadata:TargetValues", nsmgr);
            if (nodeTargetValues == null)
                throw new System.ArgumentException("Unexpected no TargetValues node found!");

            // ComponentValue
            XmlNodeList nodeList = nodeTargetValues.SelectNodes("./genericmetadata:ComponentValue", nsmgr);
            foreach (XmlNode nm in nodeList)
            {
                ComponentValueType c = new ComponentValueType(nm, nsmgr);
                _targetValuesTypeList.Add(c);
            }

            // Reported Attributes 
            nodeList = nodeArtefact.SelectNodes("./genericmetadata:ReportedAttribute", nsmgr);
            foreach (XmlNode nm in nodeList)
            {
                ReportedAttributeType r = new ReportedAttributeType(nm, nsmgr);
                _reportedAttributeList.Add(r);
            }
        }

        /// <summary>
        /// C'tor from specified Metadata structure definition and report
        /// </summary>
        /// <param name="msd"></param>
        /// <param name="rpt"></param>
        public AttributeValueSetType(MetadataStructureDefinitionType msd, ReportStructureType rpt, MetadataSetType meta)
        {
            Init(meta);
            _targetRef = msd.TargetIdentifiers.FullTargetIdentifier.Id;

            // Key identifiers
            foreach (IdentifierComponentType ic in msd.TargetIdentifiers.FullTargetIdentifier.IdentifierComponentList)
            {
                ComponentValueType c = new ComponentValueType();
                c.Value = string.Empty;
                c.Object = ic.TargetObjectClass;
                c.Component = ic.Id;
                _targetValuesTypeList.Add(c);
            }

            //Create and init Reported attributes
            rpt.MetadataAttributeList.CreateMetadatasetReportedAttributes(_reportedAttributeList);
        }

        #endregion //Construction

        #region XML serialize

        public void WriteXml(XmlTextWriter xw, string prefix, string tag)
        {
            xw.WriteStartElement(prefix, tag, null);

            // Required
            xw.WriteElementString(prefix, "TargetRef", null, TargetRef);

            // Target list
            xw.WriteStartElement(prefix, "TargetValues", null);
            foreach (ComponentValueType c in _targetValuesTypeList)
                c.WriteXml(xw, prefix, "ComponentValue");
            xw.WriteEndElement();

            // Reported Attributes 
            foreach (ReportedAttributeType r in _reportedAttributeList)
                r.WriteXml(xw, prefix, "ReportedAttribute");

            xw.WriteEndElement();
        }

        #endregion //XML serialize

        #region String Representation

        public override string ToString()
        {
            int cnt = 0;
            string msg = string.Empty;

            for (int i = _targetValuesTypeList.Count - 1; cnt < 3 && i >= 0; i--)
            {
                cnt++;
                msg += _targetValuesTypeList[i].Value;
                if (i > 0)
                    msg += ".";
            }

            if (_targetValuesTypeList.Count < 3 && _reportedAttributeList.Count > 0)
            {
                // Limit to first 80 char
                string rpt = _reportedAttributeList[0].InternationalizedValue.ToString();
                if (rpt.Length > 80)
                    rpt = rpt.Substring(0, 80) + "...";
                msg += " - " + rpt;
            }

            return msg;
        }

        #endregion //String Representation

        #region Tree Representation

        public TreeNode FillNode(TreeNode parentNode)
        {
            TreeNode t = new TreeNode(this.ToString());
            t.Tag = this;
            parentNode.Nodes.Add(t);
            return t;
        }
        #endregion

        #region ISearchIdName Members

        public MultiLang Name
        {
            get { return nameML; }
        }

        public string Id
        {
            get
            {
                return ToString();
            }
            set
            {
               ;
            }
        }
        
        #endregion
    }


    public class AttributeValueSetTypeList : List<AttributeValueSetType>
    {
    }
}
